﻿using CLM.Gestao.Administrador.DAL;
using CLM.Gestao.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CLM.Gestao.Administrador.BLL
{
    public class Periodo : PeriodoBLO<TB_PERIODO>
    {
        #region Propriedades

        public int IdPeriodo { get; set; }
        public int? MesPeriodo { get; set; }
        public string DescricaoPeriodo { get; set; }
        public PeriodoAno PeriodoAno { get; set; }
        public bool? IndicaPeriodoFechado { get; set; }
        public int? AnoPeriodo { get; set; }

        #endregion Propriedades

        #region Conversões

        private List<TB_PERIODO> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_PERIODO> List = (from l in pLista
                                     select new TB_PERIODO
                                     {
                                         ID_PERIODO = l.IdPeriodo,
                                         MES_PERIODO = l.MesPeriodo,
                                         DESCRICAO_PERIODO = l.DescricaoPeriodo,
                                         ID_PERIODO_ANO = l.IdPeriodoAno,
                                         INDICA_PERIODO_FECHADO = l.IndicaPeriodoFechado,
                                         ANO_PERIODO = l.AnoPeriodo
                                     }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_PERIODO> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    IdPeriodo = l.ID_PERIODO,
                                    MesPeriodo = l.MES_PERIODO,
                                    DescricaoPeriodo = l.DESCRICAO_PERIODO,
                                    IdPeriodoAno = l.ID_PERIODO_ANO,
                                    IndicaPeriodoFechado = l.INDICA_PERIODO_FECHADO,
                                    IndicaPeriodoAnoFechado = l.TB_PERIODO_ANO.INDICA_EXERCICIO_FECHADO,
                                    AnoPeriodo = l.ANO_PERIODO
                                }).ToList();
            return List;
        }

        #endregion Conversões

        #region CRUD

        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private IQueryable<TB_PERIODO> Get(Lista pPesquisa)
        {
            IQueryable<TB_PERIODO> Consulta;

            Consulta = from p in GetAll()
                       orderby p.ANO_PERIODO, p.MES_PERIODO
                       select p;

            if (pPesquisa != null)
            {
                if (pPesquisa.IdPeriodo > 0)
                    Consulta = from p in Consulta where p.ID_PERIODO == pPesquisa.IdPeriodo select p;

                if (pPesquisa.MesPeriodo != null)
                    Consulta = from p in Consulta where p.MES_PERIODO == pPesquisa.MesPeriodo select p;

                if (!string.IsNullOrWhiteSpace(pPesquisa.DescricaoPeriodo))
                    Consulta = from p in Consulta where p.DESCRICAO_PERIODO.Contains(pPesquisa.DescricaoPeriodo) select p;

                if (pPesquisa.AnoPeriodo != null)
                    Consulta = from p in Consulta where p.ANO_PERIODO == pPesquisa.AnoPeriodo select p;

                if (pPesquisa.IndicaPeriodoFechado != null)
                    Consulta = from p in Consulta where p.INDICA_PERIODO_FECHADO == pPesquisa.IndicaPeriodoFechado select p;

                if (pPesquisa.IndicaPeriodoAnoFechado != null)
                    Consulta = from p in Consulta where p.TB_PERIODO_ANO.INDICA_EXERCICIO_FECHADO == pPesquisa.IndicaPeriodoAnoFechado select p;

                if (pPesquisa.OrderByDescending != null)
                    Consulta = Consulta.OrderByDescending(o => new { o.ANO_PERIODO, o.MES_PERIODO }).Select(s => s);
            }

            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            var ListaUsuario = ConvertToContext(Get(pPesquisa));
            return ListaUsuario;
        }

        public List<Itens> GetItens()
        {
            return GetItens(new Lista());
        }

        public List<Itens> GetItens(Lista pPesquisa)
        {
            List<Itens> ListaUsuario = (from l in Get(pPesquisa)
                                        select new Itens
                                        {
                                            IdPeriodo = l.ID_PERIODO,
                                            MesPeriodo = l.MES_PERIODO,
                                            DescricaoPeriodo = l.DESCRICAO_PERIODO,
                                            IndicaPeriodoFechado = l.INDICA_PERIODO_FECHADO,
                                            AnoPeriodo = l.ANO_PERIODO,
                                            IdPeriodoAno = l.ID_PERIODO_ANO
                                        }).ToList();
            return ListaUsuario;
        }

        #endregion Retorna Listas e Itens

        #region Consultas

        public Periodo RecuperaPeriodoAtivo()
        {
            List<TB_PERIODO> ListaUsuario = (from l in Get(new Lista() { IndicaPeriodoAnoFechado = false, IndicaPeriodoFechado = false })
                                             select l).OrderBy(o => new { o.ANO_PERIODO, o.MES_PERIODO }).ToList();

            Periodo retorno = new Periodo();
            if (ListaUsuario != null && ListaUsuario.Count() > 0)
            {
                retorno = (from l in ListaUsuario
                           select new Periodo
                           {
                               IdPeriodo = l.ID_PERIODO,
                               MesPeriodo = l.MES_PERIODO,
                               DescricaoPeriodo = l.DESCRICAO_PERIODO,
                               IndicaPeriodoFechado = l.INDICA_PERIODO_FECHADO,
                               AnoPeriodo = l.ANO_PERIODO
                           }).First();
            }
            return retorno;
        }

        #endregion Consultas

        #region Processos

        public void EncerrarPeriodoAtivo()
        {
            Lista Ativo = GetLista(new Lista() { IndicaPeriodoAnoFechado = false, IndicaPeriodoFechado = false }).First();

            this.Update(new TB_PERIODO
            {
                ID_PERIODO = Ativo.IdPeriodo,
                ID_PERIODO_ANO = Ativo.IdPeriodoAno,
                INDICA_PERIODO_FECHADO = true,
                ANO_PERIODO = Ativo.AnoPeriodo,
                DESCRICAO_PERIODO = Ativo.DescricaoPeriodo,
                MES_PERIODO = Ativo.MesPeriodo
            });

            if (Ativo.MesPeriodo == 12)
            {
                PeriodoAno PeriodoAno = new BLL.PeriodoAno();
                PeriodoAno.Update(
                    PeriodoAno.GetLista(new PeriodoAno.Lista() { AnoPeriodo = Ativo.AnoPeriodo.ToString() })
                        .Select(s => new TB_PERIODO_ANO()
                        {
                            ID_PERIODO_ANO = s.IdPeriodoAno,
                            ANO_EXERCICIO = s.AnoPeriodo,
                            INDICA_EXERCICIO_FECHADO = true
                        }).First());

                if (this.GetItens(new Lista() { AnoPeriodo = (int)Ativo.AnoPeriodo + 1 }).Count() == 0)
                    PeriodoAno.NovoPeriodoAno((int)Ativo.AnoPeriodo + 1);
            }
        }

        #endregion Processos

        #region Classes

        /// <summary>
        /// Preenche o combobox
        /// </summary>
        public class Itens
        {
            public int IdPeriodo { get; set; }
            public int? MesPeriodo { get; set; }
            public string DescricaoPeriodo { get; set; }
            public bool? IndicaPeriodoFechado { get; set; }
            public int? AnoPeriodo { get; set; }
            public int? IdPeriodoAno { get; set; }
        }

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public int IdPeriodo { get; set; }
            public int? MesPeriodo { get; set; }
            public string DescricaoPeriodo { get; set; }
            public bool? IndicaPeriodoFechado { get; set; }
            public int? AnoPeriodo { get; set; }
            public int? IdPeriodoAno { get; set; }
            public bool? IndicaPeriodoAnoFechado { get; set; }
            public bool? OrderByDescending { get; set; }
        }

        #endregion
    }

    public class PeriodoBLO<T> : IBLO<T> where T : TB_PERIODO
    {
        private PeriodoDAO<T> _base = new PeriodoDAO<T>();
        public T Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            return _base.Save(pEntity);

        }

        public T Save(T pEntity)
        {
            Validate(pEntity);
            return _base.Save(pEntity);
        }

        public void Delete(T pEntity)
        {
            _base.Delete(pEntity);
            _base.Save(pEntity);
        }

        public T Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            return _base.Save(pEntity);
        }

        public IQueryable<T> GetAll()
        {
            return _base.GetAll();
        }

        public void Validate(T pEntity)
        {

        }
    }
}